#include <iostream>
#include <vector>
#include <string>
#include <functional>
#include <unordered_map>
#include <memory>
#include <unistd.h>

using std::cout;
using std::endl;
using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
class TimerTask
{
public:
    TimerTask(uint64_t id, uint32_t delay,const TaskFunc &cb)
        :_id(id),_timeout(delay),_task_cb(cb),_canceled(false)
    {}
    void SetRelease(const ReleaseFunc &cb)
    {
        _release = cb;
    }

    uint32_t DelayTime()
    {
        return _timeout;
    }

    void Cancel()
    {
        _canceled = true;
    }

    ~TimerTask()
    {
        if(_canceled == false) _task_cb();//定时任务没有被取消才会执行
        _release();
    }
private:
    uint64_t _id;//定时器任务对象ID
    uint32_t _timeout;//定时任务的超时时间
    TaskFunc _task_cb;//定时器对象要执行的定时任务
    ReleaseFunc _release;//用于删除TimerWheel中保存的定时器对象信息
    bool _canceled; //false-表示任务没有被取消，  true-表示任务被取消
};

class TimerWheel
{
public:
    TimerWheel()
        :_capacity(60),_tick(0),_wheel(_capacity)
    {}
    void TimerAdd(u_int64_t id, uint32_t delay, const TaskFunc &cb)//添加定时任务
    {
        PtrTask pt(new TimerTask(id,delay,cb));
        pt->SetRelease(std::bind(&TimerWheel::RemoveTimer,this,id));
        _timers[id] = WeakTask(pt);
        int pos = (_tick + delay) % _capacity;
        _wheel[pos].push_back(pt);
    }
    //刷新/延迟定时任务
    void TimerRefresh(u_int64_t id)
    {
        //通过保存我的定时器对象的weak_ptr构造一个shared_ptr出来，添加到轮子中
        auto it = _timers.find(id);
        if(it == _timers.end())
        {
            return;//没有找到定时任务，没法刷新，没法延迟
        }
        PtrTask pt = it->second.lock();//lock获取weak_ptr管理的对象对应的shared_ptr
        int delay = pt->DelayTime();
        int pos = (_tick + delay) % _capacity;
        _wheel[pos].push_back(pt);
    }

    //这个函数应该每秒钟执行一次，相当于秒针向后走了一步
    void RunTimerTask()
    {
        _tick = (_tick + 1) % _capacity;
        _wheel[_tick].clear();
    }

    //取消定时任务
    void TimerCancel(uint64_t id)
    {
        auto it = _timers.find(id);
        if(it == _timers.end())
        {
            return;//没有找到定时任务，没法刷新，没法延迟
        }
        PtrTask pt = it->second.lock();
        if(pt) pt->Cancel();
    }
private:
    void RemoveTimer(uint64_t id)
    {
        auto it = _timers.find(id);
        if(it != _timers.end())
        {
            _timers.erase(it);
        }
    }
private:
    using PtrTask = std::shared_ptr<TimerTask>;
    using WeakTask = std::weak_ptr<TimerTask>;
    int _tick; //当前的秒针，走到哪里释放哪里，就相当于执行哪里的任务 
    int _capacity; //表盘最大数量---其实就是最大延迟时间
    std::vector<std::vector<PtrTask>> _wheel;
    std::unordered_map<uint64_t, WeakTask> _timers;
};

class Test
{
public:
    Test() {cout << "构造" << endl;}
    ~Test() {cout << "析构" <<endl;}
};

void DelTest(Test *t)
{
    delete t;
}
int main()
{
    TimerWheel tw;
    Test *t = new Test();
    tw.TimerAdd(888,5,std::bind(DelTest, t));

    for(int i = 0; i < 5; i++)
    {
        sleep(1);
        tw.TimerRefresh(888);//刷新定时任务
        tw.RunTimerTask();
        cout << "刷新了一下定时任务，重新需要5s中后才会销毁" << endl;
    }
    // tw.TimerCancel(888);//取消定时任务就不会被销毁了
    while(1)
    {
        sleep(1);
        cout << "-----------------" << endl;
        tw.RunTimerTask();
    }
    return 0;
}